package com.shuke.medical.insure.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import jdk.nashorn.internal.objects.NativeString;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;


/***
 * @title CommonUtil
 * @description
 * @author woo hua
 * @version 1.0.0
 * @create 2023/4/4 10:05
 **/
@Slf4j
public class CommonUtil {


    public static SortedMap<String, Object> objectToMap(Object object) {
        if (object == null) {
            return null;
        }
        List<Field> fieldList = new ArrayList<>();
        for (Class clazz = object.getClass(); clazz != null; clazz = clazz.getSuperclass()) {
            fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
        }
        SortedMap<String, Object> res = new TreeMap<>();
        for (Field field : fieldList) {
            field.setAccessible(true);
            try {
                if (field.get(object) instanceof List) {
                    res.put(field.getName(), JSON.toJSON(field.get(object)));
                } else {
                    res.put(field.getName(), field.get(object));
                }
            } catch (IllegalAccessException e) {
                log.error("get obj field error", e);
            }
        }
        return res;
    }

    private static String getParamsFromMap(SortedMap<String, Object> map) {
        String value;
        StringBuilder sb = new StringBuilder();
        for (String key : map.keySet()) {
            Object val = map.get(key);
            if (null != val && !Objects.equals(key, "signData") && !Objects.equals(key, "encData") && !Objects.equals(key, "extra")) {
                if (isBaseDataType(val.getClass())) {
                    value = val.toString();
                } else {
                    value = JSON.toJSONString(val, new SerializerFeature[]{SerializerFeature.MapSortField});
                }
                if (!value.trim().equals("")) {
                    if (sb.length() > 0) {
                        sb.append("&");
                    }
                    sb.append(key);
                    sb.append("=");
                    sb.append(value);
                }
            }
        }
        return sb.toString();
    }

    private static boolean isBaseDataType(Class clazz) {
        return clazz.equals(String.class) || clazz.equals(Integer.class) || clazz.equals(Byte.class) || clazz.equals(Long.class) || clazz.equals(Double.class) || clazz.equals(Float.class) || clazz.equals(Character.class) || clazz.equals(Short.class) || clazz.equals(BigDecimal.class) || clazz.equals(BigInteger.class) || clazz.equals(Boolean.class) || clazz.equals(Date.class) || clazz.isPrimitive();
    }

    public static String getSignStr(String appSecret, Map<String, Object> param) {
        SortedMap<String, Object> paramMap = new TreeMap<>(param);
        String sortStr = getParamsFromMap(paramMap) + "&key=" + appSecret;
        log.info("待签名字符串：" + sortStr);
        return sortStr;
    }

    public static String stringToHexString(String s) {
        String str = "";
        for (int i = 0; i < s.length(); i++) {
            int ch = s.charAt(i);
            String s4 = Integer.toHexString(ch);
            str = str + s4;
        }
        return str;
    }

    public static String byteArrayToHex(byte[] byteArray) {
        char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
        char[] resultCharArray = new char[byteArray.length * 2];
        int index = 0;
        for (byte b : byteArray) {
            int i = index;
            int index2 = index + 1;
            resultCharArray[i] = hexDigits[(b >>> 4) & 15];
            index = index2 + 1;
            resultCharArray[index2] = hexDigits[b & 15];
        }
        return new String(resultCharArray).toUpperCase();
    }

    public static String byteToHex(byte[] b) {
        String str;
        if (b == null) {
            throw new IllegalArgumentException("Argument b ( byte array ) is null! ");
        }
        String hs = "";
        for (byte b2 : b) {
            String stmp = Integer.toHexString(b2 & 255);
            if (stmp.length() == 1) {
                str = hs + "0" + stmp;
            } else {
                str = hs + stmp;
            }
            hs = str;
        }
        return hs.toUpperCase();
    }

    public static List<String> getStrList(String inputString, int length, int size) {
        List<String> list = new ArrayList<>();
        for (int index = 0; index < size; index++) {
            String childStr = NativeString.substring(inputString, index * length, (index + 1) * length);
            list.add(childStr);
        }
        return list;
    }

    public static String valueToString(JSONObject jsonObj) {
        if (jsonObj != null) {
            Set<String> set = new HashSet<>();
                // json 的   keySet() 会报异常： org.json.JSONObject.keySet()Ljava/util/Set;  改为 alibaba fastjson
            for (String key : jsonObj.keySet()) {
                if (Objects.equals(jsonObj.get(key), "") || Objects.equals(jsonObj.get(key), null)) {
                    set.add(key);
                } else {
                    Object value = jsonObj.get(key);
                    if (value instanceof JSONObject) {
                        valueToString(jsonObj.getJSONObject(key));
                    } else if (value instanceof JSONArray) {
                        JSONArray jsonArray = jsonObj.getJSONArray(key);
                        Iterator it = jsonArray.iterator();
                        while (it.hasNext()) {
                            Object object = it.next();
                            valueToString((JSONObject) object);
                        }
                    } else {
                        jsonObj.put(key, jsonObj.get(key).toString());
                    }
                }
            }
            for (String setStr : set) {
                jsonObj.remove(setStr);
            }
        }
        return jsonObj.toString();
    }

}
